/*
 * Copyright 2013 Agustina Martinez-Garcia

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */
package uk.ljmu.qudexapps.manager.servlets;


import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

//import javax.activation.MimetypesFileTypeMap;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;

import eu.medsea.mimeutil.MimeType;
import eu.medsea.mimeutil.MimeUtil;


public class FileServlet extends HttpServlet {
	private transient Logger log = Logger.getLogger(FileServlet.class);
	private File tempDir;
	private List<String> fileList;
	private String fileSeparator;
	/**
	 * 
	 */
	private static final long serialVersionUID = -1240652264212197154L;

	public void setTempDir(File tempDir) {
		this.tempDir = tempDir;
	}
	public File getTempDir() {
		return tempDir;
	}
	public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		try {
			//Find file in temporary directory
			String fileName = (String) req.getParameter("fileName");
			String mimetype = (String) req.getParameter("type");
			if (fileName == null) {
				res.setStatus(HttpServletResponse.SC_NOT_FOUND);
			} else {
				processDirectory(this.tempDir);
				File foundFile = findFileInDirectory(fileName);
				if (foundFile != null && foundFile.length() > 0) {
					
					if (mimetype == null) {
						//mimetype = new MimetypesFileTypeMap().getContentType(foundFile);
						MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
					    Collection<?> mimeTypes = MimeUtil.getMimeTypes(foundFile);
					    if (!mimeTypes.isEmpty()) {
					    	MimeType mtype = (MimeType) mimeTypes.iterator().next();
					    	mimetype = mtype.toString();
					    }
					}
					res.setContentType(mimetype);
					res.setHeader("Content-Disposition", "inline; filename=\"" + fileName + "\"");
					res.setStatus(HttpServletResponse.SC_OK);
					ServletOutputStream out = res.getOutputStream();
					// AMG ADDED to AVOID Memory heap exceptions in Java
					IOUtils.copy(new FileInputStream(foundFile), out);
					//out.write(FileServlet.getBytesFromFile(foundFile));
					out.flush();
					out.close();
				}// if
			}
		} catch(Exception e) {
			log.fatal(e.getMessage());
		}
	}
	public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		log.info("File servlet doPost....");
		doGet(req,res);
	}
	
	/**
	 * 
	 * @param fileName
	 * @return
	 */
	private File findFileInDirectory(String fileName) {
	
		for(String fileElem : fileList) {
			String elemName = fileElem.substring(fileElem.lastIndexOf(fileSeparator) + 1, fileElem.length());
			if (elemName.equals(fileName)) {
				return new File(fileElem);
			}
		}
		return null;
	}
	/**
	 * 
	 * @param folder
	 */
	public void processDirectory(File folder)
	{
		FilenameFilter filter = new FilenameFilter() { 
			public boolean accept(File dir, String name) { 
				return !name.startsWith(".") && !name.startsWith("__"); 
			} 
		}; 
		File[] listOfFiles = folder.listFiles(filter);

		for (int i = 0; i < listOfFiles.length; i++) {
			if (listOfFiles[i].isFile()) {
				fileList.add(listOfFiles[i].getAbsolutePath());
			} else if (listOfFiles[i].isDirectory()) {
				processDirectory(listOfFiles[i]);
			}
		}
	}
	// Returns the contents of the file in a byte array.
	public static byte[] getBytesFromFile(File file) throws IOException {
	    InputStream is = new FileInputStream(file);

	    // Get the size of the file
	    long length = file.length();

	    // You cannot create an array using a long type.
	    // It needs to be an int type.
	    // Before converting to an int type, check
	    // to ensure that file is not larger than Integer.MAX_VALUE.
	    if (length > Integer.MAX_VALUE) {
	        // File is too large
	    }

	    // Create the byte array to hold the data
	    byte[] bytes = new byte[(int)length];

	    // Read in the bytes
	    int offset = 0;
	    int numRead = 0;
	    while (offset < bytes.length
	           && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
	        offset += numRead;
	    }

	    // Ensure all the bytes have been read in
	    if (offset < bytes.length) {
	        throw new IOException("Could not completely read file "+file.getName());
	    }

	    // Close the input stream and return bytes
	    is.close();
	    return bytes;
	}
	public void init() {
		ServletContext ctx = this.getServletContext();
		setTempDir((File) ctx.getAttribute("javax.servlet.context.tempdir"));
		fileList = new ArrayList<String>();
		fileSeparator = System.getProperty("file.separator");
	}
}
